---
id: cancellation
title: Interrupt a Workflow Execution - Python SDK
sidebar_label: Interrupt a Workflow
description: Interrupt a Workflow Execution using the Temporal Python SDK. Choose between canceling for a graceful stop or terminating for a forceful stop.
keywords:
  - cancel workflow execution
  - activity cancellation
  - terminate workflow execution
  - interrupt workflow execution
  - graceful workflow cancelation
  - forceful workflow termination
  - workflow cancelation logic
  - activity heartbeats
tags:
  - Workflows
  - Python SDK
  - Temporal SDKs
---

You can interrupt a Workflow Execution in one of the following ways:

- [Cancel](#cancellation): Canceling a Workflow provides a graceful way to stop Workflow Execution.
- [Terminate](#termination): Terminating a Workflow forcefully stops Workflow Execution.

Terminating a Workflow forcefully stops Workflow Execution.
This action resembles killing a process.

- The system records a `WorkflowExecutionTerminated` event in the Workflow History.
- The termination forcefully and immediately stops the Workflow Execution.
- The Workflow code gets no chance to handle termination.
- A Workflow Task doesn't get scheduled.

In most cases, canceling is preferable because it allows the Workflow to finish gracefully.
Terminate only if the Workflow is stuck and cannot be canceled normally.

## Cancel a Workflow Execution {#cancellation}

Canceling a Workflow provides a graceful way to stop Workflow Execution.
This action resembles sending a `SIGTERM` to a process.

- The system records a `WorkflowExecutionCancelRequested` event in the Workflow History.
- A Workflow Task gets scheduled to process the cancelation.
- The Workflow code can handle the cancelation and execute any cleanup logic.
- The system doesn't forcefully stop the Workflow.

To cancel a Workflow Execution in Python, use the [cancel()](https://python.temporal.io/temporalio.client.WorkflowHandle.html#cancel) function on the Workflow handle.

```python
await client.get_workflow_handle("your_workflow_id").cancel()
```

### Cancel an Activity from a Workflow {#cancel-activity}

Canceling an Activity from within a Workflow requires that the Activity Execution sends Heartbeats and sets a Heartbeat Timeout.
If the Heartbeat is not invoked, the Activity cannot receive a cancellation request.
When any non-immediate Activity is executed, the Activity Execution should send Heartbeats and set a [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout) to ensure that the server knows it is still working.

When an Activity is canceled, an error is raised in the Activity at the next available opportunity.
If cleanup logic needs to be performed, it can be done in a `finally` clause or inside a caught cancel error.
However, for the Activity to appear canceled the exception needs to be re-raised.

:::note

Unlike regular Activities, [Local Activities](/activities#local-activity) can be canceled if they don't send Heartbeats.
Local Activities are handled locally, and all the information needed to handle the cancellation logic is available in the same Worker process.

:::

To cancel an Activity from a Workflow Execution, call the [cancel()](https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel) method on the Activity handle that is returned from [start_activity()](https://python.temporal.io/temporalio.workflow.html#start_activity).

```python
@activity.defn
async def cancellable_activity(input: ComposeArgsInput) -> NoReturn:
    try:
        while True:
            print("Heartbeating cancel activity")
            await asyncio.sleep(0.5)
            activity.heartbeat("some details")
    except asyncio.CancelledError:
        print("Activity cancelled")
        raise


@activity.defn
async def run_activity(input: ComposeArgsInput):
    print("Executing activity")
    return input.arg1 + input.arg2

@workflow.defn
 class GreetingWorkflow:
     @workflow.run
     async def run(self, input: ComposeArgsInput) -> None:
        activity_handle = workflow.start_activity(
            cancellable_activity,
            ComposeArgsInput(input.arg1, input.arg2),
            start_to_close_timeout=timedelta(minutes=5),
            heartbeat_timeout=timedelta(seconds=30),
        )

        await asyncio.sleep(3)
        activity_handle.cancel()
```

:::note

The Activity handle is a Python task.
By calling `cancel()`, you're essentially requesting the task to be canceled.

:::

## Terminate a Workflow Execution {#termination}

Terminating a Workflow forcefully stops Workflow Execution.
This action resembles killing a process.

- The system records a `WorkflowExecutionTerminated` event in the Workflow History.
- The termination forcefully and immediately stops the Workflow Execution.
- The Workflow code gets no chance to handle termination.
- A Workflow Task doesn't get scheduled.

To terminate a Workflow Execution in Python, use the [terminate()](https://python.temporal.io/temporalio.client.WorkflowHandle.html#terminate) function on the Workflow handle.

```python
await client.get_workflow_handle("your_workflow_id").terminate()
```
